home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / ft_cut.c < prev    next >
C/C++ Source or Header  |  2009-02-26  |  13KB  |  567 lines

  1. /*
  2.  * Copyright 1996, 1999, 2000 by Paul Mattes.
  3.  *  Permission to use, copy, modify, and distribute this software and its
  4.  *  documentation for any purpose and without fee is hereby granted,
  5.  *  provided that the above copyright notice appear in all copies and that
  6.  *  both that copyright notice and this permission notice appear in
  7.  *  supporting documentation.
  8.  */
  9.  
  10. /*
  11.  *    ft_cut.c
  12.  *        File transfer, data movement logic, CUT version
  13.  */
  14.  
  15. #include <errno.h>
  16.  
  17. #include "globals.h"
  18.  
  19. #if defined(X3270_FT) /*[*/
  20.  
  21. #include "appres.h"
  22. #include "ctlr.h"
  23. #include "3270ds.h"
  24.  
  25. #include "actionsc.h"
  26. #include "ctlrc.h"
  27. #include "ft_cutc.h"
  28. #include "ft_cut_ds.h"
  29. #include "ftc.h"
  30. #include "kybdc.h"
  31. #include "popupsc.h"
  32. #include "tablesc.h"
  33. #include "telnetc.h"
  34. #include "trace_dsc.h"
  35. #include "utilc.h"
  36.  
  37. static Boolean cut_xfer_in_progress = False;
  38.  
  39. /* Data stream conversion tables. */
  40.  
  41. #define NQ        4    /* number of quadrants */
  42. #define NE        77    /* number of elements per quadrant */
  43. #define OTHER_2        2    /* "OTHER 2" quadrant (includes NULL) */
  44. #define XLATE_NULL    0xc1    /* translation of NULL */
  45.  
  46. static char alphas[NE + 1] =
  47. " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%&_()<+,-./:>?";
  48.  
  49. static struct {
  50.     unsigned char selector;
  51.     unsigned char xlate[NE];
  52. } conv[NQ] = {
  53.     {    0x5e,    /* ';' */
  54.     { 0x40,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,
  55.       0xd3,0xd4,0xd5,0xd6, 0xd7,0xd8,0xd9,0xe2, 0xe3,0xe4,0xe5,0xe6,
  56.       0xe7,0xe8,0xe9,0x81, 0x82,0x83,0x84,0x85, 0x86,0x87,0x88,0x89,
  57.       0x91,0x92,0x93,0x94, 0x95,0x96,0x97,0x98, 0x99,0xa2,0xa3,0xa4,
  58.       0xa5,0xa6,0xa7,0xa8, 0xa9,0xf0,0xf1,0xf2, 0xf3,0xf4,0xf5,0xf6,
  59.       0xf7,0xf8,0xf9,0x6c, 0x50,0x6d,0x4d,0x5d, 0x4c,0x4e,0x6b,0x60,
  60.       0x4b,0x61,0x7a,0x6e, 0x6f }
  61.     },
  62.     {    0x7e,    /* '=' */
  63.     { 0x20,0x41,0x42,0x43, 0x44,0x45,0x46,0x47, 0x48,0x49,0x4a,0x4b,
  64.       0x4c,0x4d,0x4e,0x4f, 0x50,0x51,0x52,0x53, 0x54,0x55,0x56,0x57,
  65.       0x58,0x59,0x5a,0x61, 0x62,0x63,0x64,0x65, 0x66,0x67,0x68,0x69,
  66.       0x6a,0x6b,0x6c,0x6d, 0x6e,0x6f,0x70,0x71, 0x72,0x73,0x74,0x75,
  67.       0x76,0x77,0x78,0x79, 0x7a,0x30,0x31,0x32, 0x33,0x34,0x35,0x36,
  68.       0x37,0x38,0x39,0x25, 0x26,0x27,0x28,0x29, 0x2a,0x2b,0x2c,0x2d,
  69.       0x2e,0x2f,0x3a,0x3b, 0x3f }
  70.     },
  71.     {    0x5c,    /* '*' */
  72.     { 0x00,0x00,0x01,0x02, 0x03,0x04,0x05,0x06, 0x07,0x08,0x09,0x0a,
  73.       0x0b,0x0c,0x0d,0x0e, 0x0f,0x10,0x11,0x12, 0x13,0x14,0x15,0x16,
  74.       0x17,0x18,0x19,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  75.       0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  76.       0x00,0x00,0x00,0x00, 0x00,0x3c,0x3d,0x3e, 0x00,0xfa,0xfb,0xfc,
  77.       0xfd,0xfe,0xff,0x7b, 0x7c,0x7d,0x7e,0x7f, 0x1a,0x1b,0x1c,0x1d,
  78.       0x1e,0x1f,0x00,0x00, 0x00 }
  79.     },
  80.     {    0x7d,    /* '\'' */
  81.     { 0x00,0xa0,0xa1,0xea, 0xeb,0xec,0xed,0xee, 0xef,0xe0,0xe1,0xaa,
  82.       0xab,0xac,0xad,0xae, 0xaf,0xb0,0xb1,0xb2, 0xb3,0xb4,0xb5,0xb6,
  83.       0xb7,0xb8,0xb9,0x80, 0x00,0xca,0xcb,0xcc, 0xcd,0xce,0xcf,0xc0,
  84.       0x00,0x8a,0x8b,0x8c, 0x8d,0x8e,0x8f,0x90, 0x00,0xda,0xdb,0xdc,
  85.       0xdd,0xde,0xdf,0xd0, 0x00,0x00,0x21,0x22, 0x23,0x24,0x5b,0x5c,
  86.       0x00,0x5e,0x5f,0x00, 0x9c,0x9d,0x9e,0x9f, 0xba,0xbb,0xbc,0xbd,
  87.       0xbe,0xbf,0x9a,0x9b, 0x00 }
  88.     }
  89. };
  90. static char table6[] =
  91.     "abcdefghijklmnopqrstuvwxyz&-.,:+ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
  92.  
  93. static int quadrant = -1;
  94. static unsigned long expanded_length;
  95. static char *saved_errmsg = CN;
  96.  
  97. #define XLATE_NBUF    4
  98. static int xlate_buffered = 0;            /* buffer count */
  99. static int xlate_buf_ix = 0;            /* buffer index */
  100. static unsigned char xlate_buf[XLATE_NBUF];    /* buffer */
  101.  
  102. static void cut_control_code(void);
  103. static void cut_data_request(void);
  104. static void cut_retransmit(void);
  105. static void cut_data(void);
  106.  
  107. static void cut_ack(void);
  108. static void cut_abort(const char *s, unsigned short reason);
  109.  
  110. static unsigned from6(unsigned char c);
  111. static int xlate_getc(void);
  112.  
  113. /*
  114.  * Convert a buffer for uploading (host->local).  Overwrites the buffer.
  115.  * Returns the length of the converted data.
  116.  * If there is a conversion error, calls cut_abort() and returns -1.
  117.  */
  118. static int
  119. upload_convert(unsigned char *buf, int len)
  120. {
  121.     unsigned char *ob0 = buf;
  122.     unsigned char *ob = ob0;
  123.  
  124.     while (len--) {
  125.         unsigned char c = *buf++;
  126.         char *ixp;
  127.         int ix;
  128.         int oq = -1;
  129.  
  130.         retry:
  131.         if (quadrant < 0) {
  132.             /* Find the quadrant. */
  133.             for (quadrant = 0; quadrant < NQ; quadrant++) {
  134.                 if (c == conv[quadrant].selector)
  135.                     break;
  136.             }
  137.             if (quadrant >= NQ) {
  138.                 cut_abort(get_message("ftCutConversionError"),
  139.                     SC_ABORT_XMIT);
  140.                 return -1;
  141.             }
  142.             continue;
  143.         }
  144.  
  145.         /* Make sure it's in a valid range. */
  146.         if (c < 0x40 || c > 0xf9) {
  147.             cut_abort(get_message("ftCutConversionError"),
  148.                 SC_ABORT_XMIT);
  149.             return -1;
  150.         }
  151.  
  152.         /* Translate to a quadrant index. */
  153.         ixp = strchr(alphas, ebc2asc[c]);
  154.         if (ixp == (char *)NULL) {
  155.             /* Try a different quadrant. */
  156.             oq = quadrant;
  157.             quadrant = -1;
  158.             goto retry;
  159.         }
  160.         ix = ixp - alphas;
  161.  
  162.         /*
  163.          * See if it's mapped by that quadrant, handling NULLs
  164.          * specially.
  165.          */
  166.         if (quadrant != OTHER_2 && c != XLATE_NULL &&
  167.             !conv[quadrant].xlate[ix]) {
  168.             /* Try a different quadrant. */
  169.             oq = quadrant;
  170.             quadrant = -1;
  171.             goto retry;
  172.         }
  173.  
  174.         /* Map it. */
  175.         c = conv[quadrant].xlate[ix];
  176.         if (ascii_flag && cr_flag && (c == '\r' || c == 0x1a))
  177.             continue;
  178.         if (ascii_flag && remap_flag)
  179.             c = ft2asc[c];
  180.         *ob++ = c;
  181.     }
  182.  
  183.     return ob - ob0;
  184. }
  185.  
  186. /* Convert a buffer for downloading (local->host). */
  187. static int
  188. download_convert(unsigned const char *buf, unsigned len, unsigned char *xobuf)
  189. {
  190.     unsigned char *ob0 = xobuf;
  191.     unsigned char *ob = ob0;
  192.  
  193.     while (len--) {
  194.         unsigned char c = *buf++;
  195.         unsigned char *ixp;
  196.         unsigned ix;
  197.         int oq;
  198.  
  199.         /* Handle nulls separately. */
  200.         if (!c) {
  201.             if (quadrant != OTHER_2) {
  202.                 quadrant = OTHER_2;
  203.                 *ob++ = conv[quadrant].selector;
  204.             }
  205.             *ob++ = XLATE_NULL;
  206.             continue;
  207.         }
  208.  
  209.         /* Translate. */
  210.         if (ascii_flag && remap_flag)
  211.             c = asc2ft[c];
  212.  
  213.         /* Quadrant already defined. */
  214.         if (quadrant >= 0) {
  215.             ixp = (unsigned char *)memchr(conv[quadrant].xlate, c,
  216.                             NE);
  217.             if (ixp != (unsigned char *)NULL) {
  218.                 ix = ixp - conv[quadrant].xlate;
  219.                 *ob++ = cg2ebc[asc2cg[(int)alphas[ix]]];
  220.                 continue;
  221.             }
  222.         }
  223.  
  224.         /* Locate a quadrant. */
  225.         oq = quadrant;
  226.         for (quadrant = 0; quadrant < NQ; quadrant++) {
  227.             if (quadrant == oq)
  228.                 continue;
  229.             ixp = (unsigned char *)memchr(conv[quadrant].xlate, c,
  230.                     NE);
  231.             if (ixp == (unsigned char *)NULL)
  232.                 continue;
  233.             ix = ixp - conv[quadrant].xlate;
  234.             *ob++ = conv[quadrant].selector;
  235.             *ob++ = cg2ebc[asc2cg[(int)alphas[ix]]];
  236.             break;
  237.         }
  238.         if (quadrant >= NQ) {
  239.             quadrant = -1;
  240.             fprintf(stderr, "Oops\n");
  241.             continue;
  242.         }
  243.     }
  244.     return ob - ob0;
  245. }
  246.  
  247. /*
  248.  * Main entry point from ctlr.c.
  249.  * We have received what looks like an appropriate message from the host.
  250.  */
  251. void
  252. ft_cut_data(void)
  253. {
  254.     switch (cg2ebc[screen_buf[O_FRAME_TYPE]]) {
  255.         case FT_CONTROL_CODE:
  256.         cut_control_code();
  257.         break;
  258.         case FT_DATA_REQUEST:
  259.         cut_data_request();
  260.         break;
  261.         case FT_RETRANSMIT:
  262.         cut_retransmit();
  263.         break;
  264.         case FT_DATA:
  265.         cut_data();
  266.         break;
  267.         default:
  268.         trace_ds("< FT unknown 0x%02x\n",
  269.             cg2ebc[screen_buf[O_FRAME_TYPE]]);
  270.         cut_abort(get_message("ftCutUnknownFrame"), SC_ABORT_XMIT);
  271.         break;
  272.     }
  273. }
  274.  
  275. /*
  276.  * Process a control code from the host.
  277.  */
  278. static void
  279. cut_control_code(void)
  280. {
  281.     unsigned short code;
  282.     char *buf;
  283.     char *bp;
  284.     int i;
  285.  
  286.     trace_ds("< FT CONTROL_CODE ");
  287.     code = (cg2ebc[screen_buf[O_CC_STATUS_CODE]] << 8) |
  288.         cg2ebc[screen_buf[O_CC_STATUS_CODE + 1]];
  289.     switch (code) {
  290.         case SC_HOST_ACK:
  291.         trace_ds("HOST_ACK\n");
  292.         cut_xfer_in_progress = True;
  293.         expanded_length = 0;
  294.         quadrant = -1;
  295.         xlate_buffered = 0;
  296.         cut_ack();
  297.         ft_running(True);
  298.         break;
  299.         case SC_XFER_COMPLETE:
  300.         trace_ds("XFER_COMPLETE\n");
  301.         cut_ack();
  302.         cut_xfer_in_progress = False;
  303.         ft_complete((String)NULL);
  304.         break;
  305.         case SC_ABORT_FILE:
  306.         case SC_ABORT_XMIT:
  307.         trace_ds("ABORT\n");
  308.         cut_xfer_in_progress = False;
  309.         cut_ack();
  310.         if (ft_state == FT_ABORT_SENT && saved_errmsg != CN) {
  311.             buf = saved_errmsg;
  312.             saved_errmsg = CN;
  313.         } else {
  314.             bp = buf = Malloc(81);
  315.             for (i = 0; i < 80; i++)
  316.                 *bp++ = cg2asc[screen_buf[O_CC_MESSAGE + i]];
  317.             *bp-- = '\0';
  318.             while (bp >= buf && *bp == ' ')
  319.                 *bp-- = '\0';
  320.             if (bp >= buf && *bp == '$')
  321.                 *bp-- = '\0';
  322.             while (bp >= buf && *bp == ' ')
  323.                 *bp-- = '\0';
  324.             if (!*buf)
  325.                 strcpy(buf, get_message("ftHostCancel"));
  326.         }
  327.         ft_complete(buf);
  328.         Free(buf);
  329.         break;
  330.         default:
  331.         trace_ds("unknown 0x%04x\n", code);
  332.         cut_abort(get_message("ftCutUnknownControl"), SC_ABORT_XMIT);
  333.         break;
  334.     }
  335. }
  336.  
  337. /*
  338.  * Process a data request from the host.
  339.  */
  340. static void
  341. cut_data_request(void)
  342. {
  343.     unsigned char seq = screen_buf[O_DR_FRAME_SEQ];
  344.     int count;
  345.     unsigned char cs;
  346.     int c;
  347.     int i;
  348.     unsigned char attr;
  349.  
  350.     trace_ds("< FT DATA_REQUEST %u\n", from6(seq));
  351.     if (ft_state == FT_ABORT_WAIT) {
  352.         cut_abort(get_message("ftUserCancel"), SC_ABORT_FILE);
  353.         return;
  354.     }
  355.  
  356.     /* Copy data into the screen buffer. */
  357.     count = 0;
  358.     while (count < O_UP_MAX && (c = xlate_getc()) != EOF) {
  359.         ctlr_add(O_UP_DATA + count, ebc2cg[c], 0);
  360.         count++;
  361.     }
  362.  
  363.     /* Check for errors. */
  364.     if (ferror(ft_local_file)) {
  365.         int j;
  366.         char *msg;
  367.  
  368.         /* Clean out any data we may have written. */
  369.         for (j = 0; j < count; j++)
  370.             ctlr_add(O_UP_DATA + j, 0, 0);
  371.  
  372.         /* Abort the transfer. */
  373.         msg = xs_buffer("read(%s): %s", ft_local_filename,
  374.             strerror(errno));
  375.         cut_abort(msg, SC_ABORT_FILE);
  376.         Free(msg);
  377.         return;
  378.     }
  379.  
  380.     /* Send special data for EOF. */
  381.     if (!count && feof(ft_local_file)) {
  382.         ctlr_add(O_UP_DATA, ebc2cg[EOF_DATA1], 0);
  383.         ctlr_add(O_UP_DATA+1, ebc2cg[EOF_DATA2], 0);
  384.         count = 2;
  385.     }
  386.  
  387.     /* Compute the other fields. */
  388.     ctlr_add(O_UP_FRAME_SEQ, seq, 0);
  389.     cs = 0;
  390.     for (i = 0; i < count; i++)
  391.         cs ^= cg2ebc[screen_buf[O_UP_DATA + i]];
  392.     ctlr_add(O_UP_CSUM, asc2cg[(int)table6[cs & 0x3f]], 0);
  393.     ctlr_add(O_UP_LEN, asc2cg[(int)table6[(count >> 6) & 0x3f]], 0);
  394.     ctlr_add(O_UP_LEN+1, asc2cg[(int)table6[count & 0x3f]], 0);
  395.  
  396.     /* XXX: Change the data field attribute so it doesn't display. */
  397.     attr = screen_buf[O_DR_SF];
  398.     attr = (attr & ~FA_INTENSITY) | FA_INT_ZERO_NSEL;
  399.     ctlr_add(O_DR_SF, attr, 0);
  400.  
  401.     /* Send it up to the host. */
  402.     trace_ds("> FT DATA %u\n", from6(seq));
  403.     ft_update_length();
  404.     expanded_length += count;
  405.     action_internal(Enter_action, IA_FT, CN, CN);
  406. }
  407.  
  408. /*
  409.  * (Improperly) process a retransmit from the host.
  410.  */
  411. static void
  412. cut_retransmit(void)
  413. {
  414.     trace_ds("< FT RETRANSMIT\n");
  415.     cut_abort(get_message("ftCutRetransmit"), SC_ABORT_XMIT);
  416. }
  417.  
  418. /*
  419.  * Convert an encoded integer.
  420.  */
  421. static unsigned
  422. from6(unsigned char c)
  423. {
  424.     char *p;
  425.  
  426.     c = cg2asc[c];
  427.     p = strchr(table6, c);
  428.     if (p == CN)
  429.         return 0;
  430.     return p - table6;
  431. }
  432.  
  433. /*
  434.  * Process data from the host.
  435.  */
  436. static void
  437. cut_data(void)
  438. {
  439.     static unsigned char cvbuf[O_RESPONSE - O_DT_DATA];
  440.     unsigned short raw_length;
  441.     int conv_length;
  442.     register int i;
  443.  
  444.     trace_ds("< FT DATA\n");
  445.     if (ft_state == FT_ABORT_WAIT) {
  446.         cut_abort(get_message("ftUserCancel"), SC_ABORT_FILE);
  447.         return;
  448.     }
  449.  
  450.     /* Copy and convert the data. */
  451.     raw_length = from6(screen_buf[O_DT_LEN]) << 6 |
  452.              from6(screen_buf[O_DT_LEN + 1]);
  453.     if ((int)raw_length > O_RESPONSE - O_DT_DATA) {
  454.         cut_abort(get_message("ftCutOversize"), SC_ABORT_XMIT);
  455.         return;
  456.     }
  457.     for (i = 0; i < (int)raw_length; i++)
  458.         cvbuf[i] = cg2ebc[screen_buf[O_DT_DATA + i]];
  459.  
  460.     if (raw_length == 2 && cvbuf[0] == EOF_DATA1 && cvbuf[1] == EOF_DATA2) {
  461.         trace_ds("< FT EOF\n");
  462.         cut_ack();
  463.         return;
  464.     }
  465.     conv_length = upload_convert(cvbuf, raw_length);
  466.     if (conv_length < 0)
  467.         return;
  468.  
  469.     /* Write it to the file. */
  470.     if (fwrite((char *)cvbuf, conv_length, 1, ft_local_file) == 0) {
  471.         char *msg;
  472.  
  473.         msg = xs_buffer("write(%s): %s", ft_local_filename,
  474.             strerror(errno));
  475.         cut_abort(msg, SC_ABORT_FILE);
  476.         Free(msg);
  477.     } else {
  478.         ft_length += conv_length;
  479.         ft_update_length();
  480.         cut_ack();
  481.     }
  482. }
  483.  
  484. /*
  485.  * Acknowledge a host command.
  486.  */
  487. static void
  488. cut_ack(void)
  489. {
  490.     trace_ds("> FT ACK\n");
  491.     action_internal(Enter_action, IA_FT, CN, CN);
  492. }
  493.  
  494. /*
  495.  * Abort a transfer in progress.
  496.  */
  497. static void
  498. cut_abort(const char *s, unsigned short reason)
  499. {
  500.     /* Save the error message. */
  501.     if (saved_errmsg != CN)
  502.         Free(saved_errmsg);
  503.     saved_errmsg = NewString(s);
  504.  
  505.     /* Send the abort sequence. */
  506.     ctlr_add(RO_FRAME_TYPE, ebc2cg[RFT_CONTROL_CODE], 0);
  507.     ctlr_add(RO_FRAME_SEQ, screen_buf[O_DT_FRAME_SEQ], 0);
  508.     ctlr_add(RO_REASON_CODE, ebc2cg[HIGH8(reason)], 0);
  509.     ctlr_add(RO_REASON_CODE+1, ebc2cg[LOW8(reason)], 0);
  510.     trace_ds("> FT CONTROL_CODE ABORT\n");
  511.     action_internal(PF_action, IA_FT, "2", CN);
  512.  
  513.     /* Update the in-progress pop-up. */
  514.     ft_aborting();
  515. }
  516.  
  517. /*
  518.  * Get the next translated character from the local file.
  519.  * Returns the character (in EBCDIC), or EOF.
  520.  */
  521. static int
  522. xlate_getc(void)
  523. {
  524.     int r;
  525.     int c;
  526.     unsigned char cc;
  527.     unsigned char cbuf[4];
  528.     int nc;
  529.  
  530.     /* If there is a data buffered, return it. */
  531.     if (xlate_buffered) {
  532.         r = xlate_buf[xlate_buf_ix];
  533.         xlate_buf_ix++;
  534.         xlate_buffered--;
  535.         return r;
  536.     }
  537.  
  538.     /* Get the next byte from the file. */
  539.     c = fgetc(ft_local_file);
  540.     if (c == EOF)
  541.         return c;
  542.     ft_length++;
  543.  
  544.     /* Expand it. */
  545.     if (ascii_flag && cr_flag && c == '\n') {
  546.         nc = download_convert((unsigned const char *)"\r", 1, cbuf);
  547.     } else
  548.         nc = 0;
  549.  
  550.     /* Convert it. */
  551.     cc = (unsigned char)c;
  552.     nc += download_convert(&cc, 1, &cbuf[nc]);
  553.  
  554.     /* Return it and buffer what's left. */
  555.     r = cbuf[0];
  556.     if (nc > 1) {
  557.         int i;
  558.  
  559.         for (i = 1; i < nc; i++)
  560.             xlate_buf[xlate_buffered++] = cbuf[i];
  561.         xlate_buf_ix = 0;
  562.     }
  563.     return r;
  564. }
  565.  
  566. #endif /*]*/
  567.